package com.rescue.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rescue.constant.MessageConstant;
import com.rescue.constant.StatusConstant;
import com.rescue.constant.SysSettingConstant;
import com.rescue.context.BaseContext;
import com.rescue.exception.AccountNotFoundException;
import com.rescue.exception.BaseException;
import com.rescue.exception.PasswordErrorException;
import com.rescue.forum.dto.*;
import com.rescue.forum.entity.EmailCode;
import com.rescue.forum.entity.RescueMan;
import com.rescue.forum.entity.UserInfo;
import com.rescue.forum.entity.UserMessage;
import com.rescue.forum.vo.AdminLoginVO;
import com.rescue.forum.vo.UserLoginVO;
import com.rescue.forum.vo.UserQueryVO;
import com.rescue.mapper.*;
import com.rescue.result.PageResult;
import com.rescue.service.UserInfoService;
import com.rescue.utils.IpUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private EmailCodeMapper emailCodeMapper;
    @Autowired
    private SysSettingMapper sysSettingMapper;
    @Autowired
    private UserMessageMapper userMessageMapper;
    @Autowired
    private RescueManMapper rescueManMapper;

    /**
     * 登录效验
     *
     * @param adminLoginDTO
     * @return
     */
    public AdminLoginVO login(AdminLoginDTO adminLoginDTO) {
        String nickName = adminLoginDTO.getNickName();
        String password = adminLoginDTO.getPassword();
        AdminLoginVO adminLoginVO = new AdminLoginVO();
        //根据用户名查询数据库
        UserInfo userInfo = userInfoMapper.getByNickName(nickName);
        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (userInfo == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        //密码比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(userInfo.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        BeanUtils.copyProperties(userInfo, adminLoginVO);
        return adminLoginVO;
    }

    /**
     * 条件查询用户列表
     *
     * @param userQueryDTO
     * @return
     */
    public PageResult page(UserQueryDTO userQueryDTO) {
        PageHelper.startPage(userQueryDTO.getPage(), userQueryDTO.getPageSize());
        Page<UserInfo> page = userInfoMapper.getList(userQueryDTO);
        List<UserInfo> userInfos = page.getResult();
        List<UserQueryVO> userInfoVos = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            UserQueryVO userQueryVO = new UserQueryVO();
            BeanUtils.copyProperties(userInfo, userQueryVO);
            userInfoVos.add(userQueryVO);
        });
        return new PageResult(page.getTotal(), userInfoVos);
    }

    /**
     * 启用或禁用用户
     *
     * @param status
     * @param userId
     */
    public void updateUserStatus(Integer status, Integer userId) {
        UserInfo userInfo = UserInfo.builder().userId(userId).status(status).build();
        userInfoMapper.update(userInfo);
    }

    /**
     * 修改积分
     *
     * @param sendMessageDTO
     */
    public void updateIntegral(SendMessageDTO sendMessageDTO) {
        UserInfo userInfo = UserInfo.builder().userId(sendMessageDTO.getUserId())
                .currentIntegral(sendMessageDTO.getIntegral())
                .totalIntegral(sendMessageDTO.getIntegral()).build();
        userInfoMapper.update(userInfo);
    }


    /**
     * 客户端注册
     *
     * @param userRegisterDTO
     */
    @Transactional
    public void register(UserRegisterDTO userRegisterDTO, HttpServletRequest request) {
        //校验昵称是否已存在
        String nickName = userRegisterDTO.getNickName();
        UserInfo byNickName = userInfoMapper.getByNickName(nickName);
        if (byNickName != null) {
            throw new BaseException(MessageConstant.NICKNAME_EXISTS);
        }
        //用户名是否已存在
        String username = userRegisterDTO.getUsername();
        UserInfo byUserName = userInfoMapper.getByUserName(username);
        if (byUserName != null) {
            throw new BaseException(MessageConstant.USERNAME_EXISTS);
        }
        //校验验证码是否正确
        String emailCode = userRegisterDTO.getEmailCode();
        String o = (String) redisTemplate.opsForValue().get(request.getRemoteAddr() + "code");

        if (o == null) {
            throw new BaseException(MessageConstant.THE_CAPTCHA_IS_WRONG);
        }
        if (!emailCode.equals(o)) {
            throw new BaseException(MessageConstant.THE_CAPTCHA_IS_WRONG);
        }
        //注册加入user表
        UserInfo userInfo = UserInfo.builder().totalIntegral(100)
                .currentIntegral(100)
                .joinTime(LocalDateTime.now())
                .email(userRegisterDTO.getEmail())
                .username(username)
                .nickName(nickName)
                .password(DigestUtils.md5DigestAsHex(userRegisterDTO.getPassword().getBytes()))
                .status(StatusConstant.ENABLE).build();
        userInfoMapper.insert(userInfo);
        //添加email表
        EmailCode newEmailCode = EmailCode.builder().code(String.valueOf(UUID.randomUUID()))
                .createTime(LocalDateTime.now())
                .email(userRegisterDTO.getEmail())
                .status(StatusConstant.ENABLE).build();
        emailCodeMapper.insert(newEmailCode);
        //查询系统设置
        String s = sysSettingMapper.getByCode(SysSettingConstant.REGISTER_SETTING);
        HashMap<String, String> map = (HashMap<String, String>) JSON.parseObject(s, Map.class);
        //添加一条系统消息
        UserMessage message = UserMessage.builder().receivedUserId(userInfo.getUserId())
                .createTime(LocalDateTime.now())
                .messageType(UserMessage.TYPE_SYS_MESSAGE)
                .messageContent(map.get("registerWelcomeInfo"))
                .status(1).build();
        userMessageMapper.save(message);
        //TODO 添加一条救援人信息：默认为普通权限
        RescueMan rescueMan = RescueMan.builder().nickName(nickName)
                .isRescueMan(0)
                .userId(userInfo.getUserId()).build();
        rescueManMapper.save(rescueMan);

    }


    /**
     * 用户登录接口
     *
     * @param userLoginDTO
     * @return
     */
    @Transactional
    public UserLoginVO userLogin(UserLoginDTO userLoginDTO, HttpServletRequest request) {
        //效验用户名密码
        String username = userLoginDTO.getUsername();
        String password = userLoginDTO.getPassword();
        UserInfo byUserName = userInfoMapper.getByUserName(username);
        if (byUserName == null) {
            throw new BaseException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(byUserName.getPassword())) {
            throw new BaseException(MessageConstant.PASSWORD_ERROR);
        }
        if (byUserName.getStatus().equals(StatusConstant.DISABLE)) {
            throw new BaseException(MessageConstant.ACCOUNT_LOCKED);
        }
        //修改用户信息最后登录时间等
        UserInfo userInfo = UserInfo.builder().lastLoginIp(request.getRemoteAddr())
                .lastLoginTime(LocalDateTime.now())
                .lastLoginIpAddress(IpUtils.getLocation(request.getRemoteAddr()).getProvince())
                .userId(byUserName.getUserId())
                .build();
        userInfoMapper.update(userInfo);

        return UserLoginVO.builder().userId(userInfo.getUserId())
                .nickName(byUserName.getNickName())
                .province(userInfo.getLastLoginIpAddress())
                .build();
    }


    /**
     * 重置密码
     *
     * @param resetPwdDTO
     */
    public void resetPwd(ResetPwdDTO resetPwdDTO, HttpServletRequest request) {
        String email = resetPwdDTO.getEmail();
        UserInfo userInfo = userInfoMapper.getByEmail(email);
        //检查账号是否存在
        if (userInfo == null) {
            throw new BaseException(MessageConstant.EMAIL_IS_NOT_REGISTERED);
        }
        //检查邮箱验证码是否正确
        String emailCode = resetPwdDTO.getEmailCode();
        String o = (String) redisTemplate.opsForValue().get(request.getRemoteAddr() + "code");
        if (!emailCode.equals(o)) {
            throw new BaseException(MessageConstant.THE_CAPTCHA_IS_WRONG);
        }
        //修改密码
        String password = resetPwdDTO.getPassword();
        UserInfo info = UserInfo.builder().userId(userInfo.getUserId())
                .password(DigestUtils.md5DigestAsHex(password.getBytes())).build();
        userInfoMapper.update(info);

        UserMessage message = UserMessage.builder().messageType(UserMessage.TYPE_SYS_MESSAGE)
                .receivedUserId(userInfo.getUserId())
                .messageContent(UserMessage.CHANGE_PASSWORD)
                .createTime(LocalDateTime.now()).build();
        userMessageMapper.save(message);
    }

    /**
     * 根据id查找
     *
     * @param userId
     * @return
     */
    public UserInfo getUserInfo(Integer userId) {
        return userInfoMapper.getByUserId(userId);
    }

    /**
     * 修改个人信息
     *
     * @param userUpdateInfoDAO
     */
    public void updateUserInfo(UserUpdateInfoDAO userUpdateInfoDAO) {
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(userUpdateInfoDAO, userInfo);
        userInfo.setUserId(BaseContext.getCurrentId());
        userInfoMapper.update(userInfo);
    }
}
